package top.wintp.offlinedataanalysis.etl.utils;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Map;

import top.wintp.offlinedataanalysis.common.ConstantValues;
import top.wintp.offlinedataanalysis.common.EventLogConstant;
import top.wintp.offlinedataanalysis.util.HttpUtils;
import top.wintp.offlinedataanalysis.util.TimeUtil;

/**
 * description:
 * <p>
 * author:  upuptop
 * <p>
 * qq: 337081267
 * <p>
 * CSDN:   http://blog.csdn.net/pyfysf
 * <p>
 * cnblogs:   http://www.cnblogs.com/upuptop
 * <p>
 * blog:   http://wintp.top
 * <p>
 * email:  pyfysf@163.com
 * <p>
 * time: 2019/08/2019/8/14
 * <p>
 */
public class LogUtils {
    private static final Logger logger = LoggerFactory.getLogger(LogUtils.class);
    private static IPSeekerExt ipSeekerExt = new IPSeekerExt();

    /**
     * 检查日志 主要查看日志格式是否正确 参数个数 长度 格式是否正确
     *
     * @param line
     * @return
     * @throws Exception
     */
    public static Map<String, String> checkLog(String line) throws Exception {
        String[] items = line.split(ConstantValues.LOG_SPLIT_TAG);
        // 通过^A分割有4部分
        if (items.length != ConstantValues.LOG_ITEM_COUNT) {
            throw new Exception(String.format("数据总量不正确：总量应为【%d】，实际上为【%d】，日志文件:{%s}", ConstantValues.LOG_ITEM_COUNT, items.length, items));
        }

        //    判断最后一个字段，是否包含en字段
        String endItem = items[items.length - 1];

        if (!endItem.contains("?")) {
            throw new Exception("数据不存在参数：" + line);
        }

        endItem = endItem.substring(endItem.indexOf("?") + 1);
        //将最后一个字段转换为Map
        Map<String, String> requestParamMap = HttpUtils.conversionParam(endItem);

        //判断是否存在en为key的条目
        if (!requestParamMap.containsKey(EventLogConstant.LOG_COLUMN_NAME_EVENT)) {
            throw new Exception("数据不存在en字段：" + line);
        }

        //    判断en的值是否仅仅是6种指定的事件
        String enValue = requestParamMap.get(EventLogConstant.LOG_COLUMN_NAME_EVENT);
        if (EventLogConstant.EventEnum.valueOfAlias(enValue) == null) {
            throw new Exception(String.format("日志中的事件名称【%s】不存在", enValue));
        }

        //158.179.38.72^A1465562718.152^A59410^A/log.gif?
        // 日志格式为: ip^A服务器时间^Ahost^A请求参数
        //添加前面的字段
        requestParamMap.put(EventLogConstant.LOG_COLUMN_NAME_IP, items[0]);
        //service-time 转为long类型的对象
        requestParamMap.put(EventLogConstant.LOG_COLUMN_NAME_SERVER_TIME, String.valueOf(TimeUtil.parseNginxServerTime2Long(items[1])));

        return requestParamMap;
    }


    /**
     * 解析日志，主要是解析ip，根据ip获取国家省市，解析UserAgent，根据userAgent获取系统信息，浏览器信息等等
     *
     * @param paramMap
     */
    public static void parserLog(Map<String, String> paramMap) throws Exception {
        String ip = paramMap.get(EventLogConstant.LOG_COLUMN_NAME_IP);
        logger.info("LogUtils  parserLog()   ip   " + ip);
        String userAgent = paramMap.get(EventLogConstant.LOG_COLUMN_NAME_USER_AGENT);
        logger.info("LogUtils  parserLog()   userAgent   " + userAgent);

        //删除ip字段和userAgent
        paramMap.remove(EventLogConstant.LOG_COLUMN_NAME_IP);
        paramMap.remove(EventLogConstant.LOG_COLUMN_NAME_USER_AGENT);


        if (StringUtils.isEmpty(ip)) {
            throw new Exception("ip值为空,日志数据：" + paramMap);
        }

        if (StringUtils.isEmpty(userAgent)) {
            throw new Exception("userAgent值为空,日志数据：" + paramMap);
        }
        //解析ip 保存对应的省市
        IPSeekerExt.RegionInfo regionInfo = ipSeekerExt.analyticIp(ip);
        String country = regionInfo.getCountry();
        String province = regionInfo.getProvince();
        String city = regionInfo.getCity();
        paramMap.put(EventLogConstant.LOG_COLUMN_NAME_COUNTRY, country);
        paramMap.put(EventLogConstant.LOG_COLUMN_NAME_PROVINCE, province);
        paramMap.put(EventLogConstant.LOG_COLUMN_NAME_CITY, city);


        //url encode
        userAgent = URLDecoder.decode(userAgent, "utf-8");

        //    解析UserAgent
        UserAgentUtil.UserAgentInfo userAgentInfo = UserAgentUtil.analyticUserAgent(userAgent);
        String browserName = userAgentInfo.getBrowserName();
        String browserVersion = userAgentInfo.getBrowserVersion();
        String osName = userAgentInfo.getOsName();
        String osVersion = userAgentInfo.getOsVersion();

        paramMap.put(EventLogConstant.LOG_COLUMN_NAME_BROWSER_NAME, browserName);
        paramMap.put(EventLogConstant.LOG_COLUMN_NAME_BROWSER_VERSION, browserVersion);
        paramMap.put(EventLogConstant.LOG_COLUMN_NAME_OS_NAME, osName);
        paramMap.put(EventLogConstant.LOG_COLUMN_NAME_OS_VERSION, osVersion);
    }


}
